﻿//smin, siin


using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using System.Data.OleDb;
using MySql.Data.MySqlClient;
using System.Net;
using System.Diagnostics;

namespace GTS
{
    public partial class Form1 : Form
    {
        int lineno = 0;
        string[] mDataHeaders = { "SMIN", "SIIN" };
        string[] mTimeStampHeaders = { "AAXX" };

        StreamReader mStreamReader = null;

        string mGTSFilename = string.Empty;
        string mDataFolderPath = string.Empty;
        string mStationDetailsFilename = "StationDetails.xml";

        OpenFileDialog ofd = new OpenFileDialog();
        List<GTSData> GTSDataList = new List<GTSData>();
        List<StationDetails> mStationDetails = new List<StationDetails>();

        string mFTPFilename = "GTS";
        List<string> mPendingFilesPostFixList = new List<string>();

        string mFTPPath = "ftp://125.21.185.11//home//rthnewdelhi//";

        string mLogFolderPath = "";
        string mLogFilename = "Log_";
        StreamWriter mDebugStream = null;
        StackTrace mStackTrace = new StackTrace();

        double mPendingListInterval = 600;
        double mPendingListTimer = 0.0f;

        public Form1()
        {
            InitializeComponent();
            this.timer1.Start();
            this.PendingListTimer.Start();
            string defaultpath = Application.StartupPath;
            int startIndex = defaultpath.LastIndexOf("\\");
            defaultpath = defaultpath.Substring(0, startIndex);
            startIndex = defaultpath.LastIndexOf("\\");
            defaultpath = defaultpath.Substring(0, startIndex);
            defaultpath += "\\Data\\";
            mDataFolderPath = defaultpath;
           
            UpdateStatus("Application initialized");
            LoadStationList();
            mFTPTimer = mFTPFileTimeInterval;
            mPendingListTimer = mPendingListInterval;
            OpenDebugFile();
            Reset();
            
        }

        void OpenDebugFile()
        {
            mLogFolderPath = mDataFolderPath + "\\Logs\\";
            mLogFilename = "Log_" + DateTime.Now.ToFileTimeUtc()+".log";
            mDebugStream = new StreamWriter(mLogFolderPath + mLogFilename);
            mDebugStream.WriteLine("Application started... " + DateTime.Now.ToString());
        }

        void WriteToDebugFile(string instring)
        {
            if (mDebugStream != null)
                mDebugStream.WriteLine(instring);
        }

        void CloseDebugFile()
        {
            if (mDebugStream != null)
            {
                mDebugStream.Close();
                mDebugStream = null;
            }
        }

        void Reset()
        {
            GTSDataList.Clear();
            this.textBox1.Text = mFilenamePostfix.ToString();
        }
        void UpdateStatus(string inStr)
        {
            Status.AppendText("\n");
            Status.AppendText(inStr);
            Status.Invalidate();
        }

        private void LoadStationList()
        {
            XmlSerializer sr = new XmlSerializer(typeof(List<StationDetails>));
            FileStream fs = new FileStream(mDataFolderPath + mStationDetailsFilename, FileMode.Open, FileAccess.Read);
            if (fs != null)
            {
                mStationDetails = sr.Deserialize(fs) as List<StationDetails>;

                UpdateStatus("Station details loaded..." + mStationDetails.Count);
                fs.Close();
            }
        }

        private void LoadGTSFile_Click(object sender, EventArgs e)
        {
            ofd.Multiselect = false;

            ofd.InitialDirectory = mDataFolderPath;

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                mStreamReader = new StreamReader(ofd.FileName);
                ProcessGTSFile();
            }
        }

        #region WriteToDB

        bool IsTimeSignatureVerified(GTSData inGTSData, MySqlDataReader inReader)
        {
            bool retValue = false;
            int gtsTimeSignature = Convert.ToInt32(inGTSData.TimeSignature);
            int dbTimeSignature = Convert.ToInt32(inReader.GetInt32(2));

            int gtsDay = gtsTimeSignature/ 1000;
            int dbDay = dbTimeSignature/1000;
            float gtsTime = (gtsTimeSignature % (gtsDay *1000))/10  ;
            float dbTime = (dbTimeSignature % (dbDay *1000))/10 ;
            if (gtsDay == dbDay && gtsTime == dbTime)
            {
                UpdateStatus("updating for "+ inReader.GetInt32(1)+"    " + inGTSData.DataHeader + "   " + inGTSData.TimeSignature);
                retValue = true;
            }
            
            return retValue;
        }

        bool CheckForDuplicateRecordsInDB(GTSData inGTSData, StationRecord insr)
        {
            bool isrecordUpdated = false;
            string queryText = "select * from world.cwctable where stationid = " + insr.StationID.ToString() + " and timesignature = " + inGTSData.TimeSignature;
            MySqlCommand cmd = new MySqlCommand(queryText, mConnection);
            MySqlDataReader reader = null;
            reader = cmd.ExecuteReader();
            StationRecord sr = new StationRecord();
            
            while (reader.Read())
            {
                if (IsTimeSignatureVerified(inGTSData, reader))
                {
                    insr.MergeDataWithDB(reader);
                    isrecordUpdated = true;
                }
            }
            reader.Close();
            return isrecordUpdated;
        }

        string GetDaytimeString(string inTimeSignature)
        {
            string daytimestring = string.Empty;
            int gtsDay = Convert.ToInt32(inTimeSignature) / 1000;
            float gtsTime = (Convert.ToInt32(inTimeSignature) % (gtsDay * 1000)) / 10;
            daytimestring = gtsDay.ToString() + gtsTime.ToString();
            return daytimestring;
        }

        void WriteStationDataToDB()
        {
            foreach (GTSData gtsData in GTSDataList)
            {
                foreach (StationRecord sr in gtsData.StationRecordList)
                {
                    bool recordUpdated = CheckForDuplicateRecordsInDB(gtsData,sr);
                    string paramString = string.Empty;
                    if(!recordUpdated)
                        paramString = "DataID, TimeSignature,";
                    paramString += sr.GetParamString();
                    string valueString = string.Empty;
                    if(!recordUpdated)
                        valueString = "'" + gtsData.DataHeader + "'" + ", " + "'" + gtsData.TimeSignature + "' , " ;
                    valueString += sr.GetValueString();
                    string sqlCmd = string.Empty;
                    if (!recordUpdated)
                        sqlCmd = "INSERT INTO world.CWCTable (" + paramString + ")" + " VALUES " + "(" + valueString + ")";
                    else
                        sqlCmd = "update world.cwctable set " + sr.GetUpdateString() + " where stationid = " + sr.StationID.ToString()+" and timesignature = "+ gtsData.TimeSignature;
                    MySqlCommand cmd = new MySqlCommand(sqlCmd, mConnection);
                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (Exception ex)
                    {
                        WriteToDebugFile("Exception --    "+ex.Message);
                        WriteToDebugFile("Stack Trace -  " + Environment.StackTrace);
                        UpdateStatus("Error found : " + ex.Message);
                    }
                }
            }
        }

        MySqlConnection mConnection = null;

        void WriteGTSDataToDB()
        {
            string cs = @"server=localhost;userid=root;
            password=admin;database=MySQL";
            try
            {
                mConnection = new MySqlConnection(cs);
                mConnection.Open();
                WriteStationDataToDB();
                UpdateStatus("Writing to database complete!");

            }
            catch (MySqlException ex)
            {
                UpdateStatus("Error - " + ex.Message);
            }
            finally
            {
                if (mConnection != null)
                {
                    mConnection.Close();
                }
            }
        }
        #endregion

        #region GTS file processing

        void WriteToConsole()
        {
            foreach (GTSData gts in GTSDataList)
            {
                UpdateStatus(gts.DataHeader);
                foreach (StationRecord sr in gts.StationRecordList)
                {
                    UpdateStatus(sr.ToString());
                }
            }
        }
        void ProcessGTSFile()
        {
            if (mStreamReader == null)
            {
                UpdateStatus("File could not be opened!!");
                return;
            }

            Reset();

            // WriteXMLTags();

            ReadGTSData();

            //WriteToConsole();

            UpdateStatus("Start writing to database...");
            WriteGTSDataToDB();

            mStreamReader.Close();

        }

        bool IsHeaderFound(string inStr, string[] inHeaders, out string header)
        {
            bool retValue = false;
            header = string.Empty;
            if (!string.IsNullOrEmpty(inStr))
            {
                string[] delim = { " " };
                string[] dataArray = inStr.Split(delim, StringSplitOptions.RemoveEmptyEntries);
                if (dataArray != null && dataArray.Length > 0 && !string.IsNullOrEmpty(dataArray[0]))
                {
                    string firstWord = dataArray[0];
                    foreach (string str in inHeaders)
                    {
                        if (firstWord.StartsWith(str, StringComparison.OrdinalIgnoreCase))
                        {
                            retValue = true;
                            header = firstWord;
                            break;
                        }
                    }
                }

            }
            return retValue;
        }

        bool IsStationdIDFound(string inStationID)
        {
            bool retValue = false;
            int stationId = 0;
            try
            {
                stationId = Convert.ToInt32(inStationID);
            }
            catch (Exception ex)
            {
                
                return retValue;
            }

            foreach (StationDetails sd in mStationDetails)
            {
                if (stationId == sd.StationID)
                {
                    retValue = true;
                    break;
                }
            }

            return retValue;
        }

        bool IsLikeStationID(string inWildString)
        {
            bool retValue = false;
            int stationID = 0;
            try 
            { 
                stationID = Convert.ToInt32(inWildString);
                if((stationID / 10000) == 4)
                    retValue = true;
            }
            catch (Exception ex)
            {
               
                return retValue;
            }
            return retValue;
        }

        string ReadTimeSignature()
        {
            string retValue = string.Empty;
            bool isTimeSignatureFound = false;
            while (!isTimeSignatureFound)
            {
                string line = mStreamReader.ReadLine();
                lineno++;
                if (!string.IsNullOrEmpty(line))
                {
                    string header = string.Empty;
                    if (IsHeaderFound(line, mTimeStampHeaders, out header))
                    {
                        string[] delim = { " " };
                        string[] stringArray = line.Split(delim, StringSplitOptions.RemoveEmptyEntries);
                        if (stringArray != null && stringArray.Length > 0)
                        {
                            retValue = stringArray[1];
                            isTimeSignatureFound = true;
                        }
                    }
                }
            }
            return retValue;
        }

        bool ReadRecord(GTSData inGTSData)
        {
            bool retValue = true;
            bool headerFound = false;
            bool isRecordComplete = false;
            List<string> dataStrings = new List<string>();
            StationRecord stationRecord = new StationRecord();

            while (!isRecordComplete )
            {
                if(mStreamReader.EndOfStream) return false;
                string line = mStreamReader.ReadLine();
                lineno++;
                if (!string.IsNullOrEmpty(line))
                {

                    string[] delim = { " ", "=", "NIL" };
                    string[] stringArray = line.Split(delim, StringSplitOptions.RemoveEmptyEntries);
                    int startIndex = 0;
                    if (!headerFound)
                    {
                        //if (IsStationdIDFound(stringArray[0]))
                        if (stringArray != null && stringArray.Length>0 && IsLikeStationID(stringArray[0]))
                        {
                            stationRecord.StationID = Convert.ToInt32(stringArray[0]);
                            startIndex = 1;
                            headerFound = true;
                        }
                        else
                            return false;
                    }

                    if (headerFound)
                    {
                        if (line.Contains("=") || line.Contains("NIL"))
                            isRecordComplete = true;

                        startIndex = 0;
                        for (int i = startIndex; i < stringArray.Length; i++)
                            dataStrings.Add(stringArray[i]);

                        if (!headerFound && !isRecordComplete)
                            retValue = false;
                    }
                    else
                    {
                        retValue = false;
                        break;
                    }

                }
            }

            if (retValue)
            {
                stationRecord.SetData(dataStrings);
                if(IsStationdIDFound(dataStrings[0]))
                    inGTSData.StationRecordList.Add(stationRecord);
            }


            return retValue;
        }

        void ReadStationData(GTSData inGTSData)
        {
            bool canRead = true;

            inGTSData.TimeSignature = ReadTimeSignature();

            while (canRead)
            {
                canRead = ReadRecord(inGTSData);
            }
        }

        void ReadGTSData()
        {
            while (!mStreamReader.EndOfStream)
            {
                GTSData gtsData = new GTSData();
                string headerLine = mStreamReader.ReadLine(); lineno++;
                if (!string.IsNullOrEmpty(headerLine))
                {
                    string header = string.Empty;
                    if (IsHeaderFound(headerLine, mDataHeaders, out header))
                    {
                        gtsData.DataHeader = header;
                        ReadStationData(gtsData);
                        GTSDataList.Add(gtsData);
                    }
                }
            }
            UpdateStatus("Total Datasets - " + GTSDataList.Count);
            UpdateStatus("Endof file");
        }
        #endregion

        #region Writing Station Details to XML

        void WriteXMLTags()
        {
            string stationID = "0";

            while (!string.IsNullOrEmpty(stationID))
            {
                stationID = mStreamReader.ReadLine(); lineno++;
                int sID = Convert.ToInt32(stationID);
                mStationDetails.Add(new StationDetails(sID));
            }

            try
            {
                FileStream fs = new FileStream(mDataFolderPath + mStationDetailsFilename, FileMode.Create);
                XmlSerializer xs = new XmlSerializer(typeof(List<StationDetails>));
                xs.Serialize(fs, mStationDetails);

                fs.Close();
            }
            catch (Exception ex)
            {
                Status.Text = ex.Message;
            }

        }

        #endregion


        #region FTP
        string mFilenamePostfixString = string.Empty;
        string pFilenamePostfixString
        {
            get
            {
                if (mFilenamePostfix < 10)
                    mFilenamePostfixString = "0" + mFilenamePostfix.ToString();
                else
                    mFilenamePostfixString = mFilenamePostfix.ToString();
                return mFilenamePostfixString;
            }
            set { mFilenamePostfixString = value; }
        }
        int mFilenamePostfix = 00;
        int pFilenamePostFix
        {
            set
            {
                if (value >= 47)
                    mFilenamePostfix = 0;
                else
                    mFilenamePostfix = value;
                this.textBox1.Text = mFilenamePostfix.ToString();
               
            }
            get { return mFilenamePostfix; }
        }
      

        private void button1_Click(object sender, EventArgs e)
        {
            pFilenamePostFix = Convert.ToInt32(this.textBox1.Text);
            mPendingFilesPostFixList.Add(pFilenamePostfixString);
            mPendingListTimer = 0;
        }

        void DownloadFromFTP()
        {
            bool isSuccessfullyDownloaded = true;

            string gtsPostFix = string.Empty;
            if (mPendingFilesPostFixList.Count > 0)
                gtsPostFix = mPendingFilesPostFixList[0];
            else return;

            string ftpLocation = mFTPPath + mFTPFilename + gtsPostFix;
            
            FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(ftpLocation);
            request.Method = WebRequestMethods.Ftp.DownloadFile;

            request.Credentials = new NetworkCredential("rthnewdelhi", "rthnewdelhi");
            request.Timeout = -1;
            request.KeepAlive = false;
            request.UseBinary = true;
            FtpWebResponse response = null;
            Stream responseStream = null;
            
            try
            {
                UpdateStatus("Initiating request from FTP - for file - " + mFTPFilename + gtsPostFix);
                response = (FtpWebResponse)request.GetResponse();
            }
            catch (Exception ex)
            {
                isSuccessfullyDownloaded = false;
                UpdateStatus("failed to download GTS" +pFilenamePostfixString+"      "+"...added to pending list.");
            }

            if (isSuccessfullyDownloaded)
            {
                mPendingFilesPostFixList.Remove(gtsPostFix);
                responseStream = response.GetResponseStream();
                StreamReader sReader = new StreamReader(responseStream);
                StreamWriter sWriter = new StreamWriter(mDataFolderPath + mFTPFilename + gtsPostFix);
                string str = sReader.ReadToEnd();
                sWriter.Write(str);

                responseStream.Close();
                sReader.Close();
                sWriter.Close();
                UpdateStatus("FTP file created on disk successfully.");
                mStreamReader = new StreamReader(mDataFolderPath + mFTPFilename + gtsPostFix);
               
                ProcessGTSFile();
                response.Close();

            }
        }

        string GetTimerString(double inTime)
        {
            string retString = string.Empty;
            //int totalsecs = (int)inTime / 1000;
            int totalsecs = (int)inTime;
            int hrs = totalsecs / (60 * 60);
            int mins = (totalsecs - hrs*3600)/60;
            int seconds = totalsecs - hrs*3600 - mins*60;
            retString = hrs.ToString() + ":" + mins.ToString() + ":" + seconds.ToString();
            return retString;
        }

        double mFTPFileTimeInterval =  60 *30 ;
        double mFTPTimer = 0;
        private void timer1_Tick(object sender, EventArgs e)
        {
            mFTPTimer -= 1;
            this.label2.Text = GetTimerString(mFTPTimer);
            if (mFTPTimer <= 0)
            {
                mFTPTimer = mFTPFileTimeInterval;
                mPendingFilesPostFixList.Add(pFilenamePostfixString);
                //UpdateStatus("post fix number updated.");
                pFilenamePostFix++;
            }
        }

        
        private void PendingListTimer_Tick(object sender, EventArgs e)
        {
            mPendingListTimer-- ;
            this.label6.Text = GetTimerString(mPendingListTimer);
            this.label7.Text = "Pending File(s)  :  " + mPendingFilesPostFixList.Count.ToString(); 
            if (mPendingListTimer <= 0)
            {
                mPendingListTimer = mPendingListInterval;
                if (mPendingFilesPostFixList.Count > 0)
                    DownloadFromFTP();
            }

        }
# endregion

        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                int intervalInMins = Convert.ToInt32(textBox2.Text);
                if(intervalInMins < 5)
                    mFTPFileTimeInterval = intervalInMins * 60 * 1000;
                mFTPTimer = mFTPFileTimeInterval;
            }
            catch (Exception ex)
            {
                UpdateStatus("error in setting the interval - " + ex.Message);
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (mDebugStream != null)
                mDebugStream.Close();
            //e.Cancel = true;
            //this.Hide();
        }

        private void Form1_KeyPress(object sender, KeyPressEventArgs e)
        {
            char c = e.KeyChar;
            UpdateStatus("key pressed " + c.ToString());
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            //mPendingListInterval = Convert.ToDouble(this.textBox3.Text);
        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {
                    }

       
     }
}
